/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFVMEEvent
  \brief class for holding an event for VME daq
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-09-27
  \date 2021-09-28 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date        <th>Author      <th>Description                    </tr>
  <tr>  <td>2021-09-27   <td>Asia Sun    <td>file created                   </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFVMEEvent_h
#define ETFVMEEvent_h

#include <array>
#include <Rtypes.h>
#include "vme_event_head.h"

using std::array;

struct section_head;
class TClonesArray;

class ETFHPTDCCh;
class ETFAmpCh;
class ETFVMERawEvent;

class ETFVMEEvent{
public:
  ETFVMEEvent(int id = -1);
  ETFVMEEvent(const ETFVMEEvent &sec);
  virtual ~ETFVMEEvent();

  virtual void Reset(); ///< clear fEvent for next event
  ///@{ getters
  const vme_event_head &GetEventHead() const{ return fEventHead; }
  vme_event_head &GetEventHead(){ return fEventHead; }
  
  const array<unsigned, 16> &GetSca() const{ return fSca; }
  const array<unsigned, 16> &GetPSca() const{ return fPSca; }
  const array<int, 16> &GetDSca() const{ return fDSca; }
  array<unsigned, 16> &GetSca(){ return fSca; }
  array<unsigned, 16> &GetPSca(){ return fPSca; }
  array<int, 16> &GetDSca(){ return fDSca; }
  unsigned sca(int i) const{ return fSca[i]; }
  unsigned psca(int i) const{ return fPSca[i]; }
  int dsca(int i) const{ return fDSca[i]; }
  // v830 definition //
  unsigned t0() const{ return fSca[3]; }
  unsigned t1() const{ return fSca[4]; }

  unsigned GetBunchID() const{ return fBunchID; }
  unsigned GetEventID() const{ return fEventID; }
  TClonesArray *GetHPTDCChannels() const;
  TClonesArray *GetAmplitudeChannels() const;
  ETFVMERawEvent *GetVMERawEvent() const{ return fRawEvent; }
  TClonesArray *tchs() const{ return GetHPTDCChannels(); }
  TClonesArray *achs() const{ return GetAmplitudeChannels(); }
  ETFVMERawEvent *raw() const{ return fRawEvent; }
  ETFHPTDCCh *GetTChByChId(int chid) const;
  ETFAmpCh *GetAChByChId(int chid) const;
  const ETFHPTDCCh *tch(int chid) const{ return GetTChByChId(chid); }
  const ETFAmpCh *ach(int chid) const{ return GetAChByChId(chid); }
  bool HasTChId(int chid) const;
  bool HasAChId(int chid) const;

  double timeL(int chid, int i = 0) const; // get i-th leading time with chid
  double timeT(int chid, int i = 0) const; // get i-th trailing time with chid
  double amp(int chid) const; // get amplitude with chid

  unsigned GetEventIndex() const{ return fEvIndex; }
  unsigned Index() const{ return fEvIndex; }
  unsigned GetEventLength() const{ return fEventHead.event_length; }
  unsigned ev_len() const{ return fEventHead.event_length; }
  ///@}

  ///@{ setters
  void SetBunchID(int bunchID){ fBunchID = bunchID; }
  void SetEventID(int eventID){ fEventID = eventID; }
  ///@}

  virtual void PrintBunchID() const;
  virtual void PrintEventID() const;
  virtual void Print() const;
  int id() const{ return fId; }

  friend class ETFVMEUnpacker;

  ClassDef(ETFVMEEvent, 1); ///< VME data section class

protected:
  int fId; //! ///< the id of the unpacker this object belongs to
  // vme_event_head fEventHead; ///< containin event index and event length
  unsigned fEvIndex; ///< event index
  /// \NOTE that since VME already has its data's time stamp subtracted by trig,
  /// the bunchID has lost its value, i.e., we don't use fBunchID here to get
  /// relative time, since it is already relative
  unsigned fBunchID; ///< bunchID: trigger time tag
  unsigned fEventID; //! ///< eventID: from event counter
  /// scaler plugin for counting purposes
  array<unsigned, 16> fSca;
  array<unsigned, 16> fPSca; //! [p]revious scaler
  array<int, 16> fDSca; ///< d[elta]-scaler
  vme_event_head fEventHead;
  TClonesArray *fHPTDCChannels; //! for HPTDC time channels
  TClonesArray *fAmplitudeChannels; //! for amplitudes, e.g. MUSIC & TAC signals
  ETFVMERawEvent *fRawEvent; //!
};

#endif
